import json
import os
import shutil
from pathlib import Path
from typing import List, Dict, Any
from components.color_trigger import ColorTriggerItem

class ConfigManager:
    """配置文件管理器（优化版本 - 支持缓存和批量操作）"""

    def __init__(self, config_dir: str = "config"):
        self.config_dir = Path(config_dir)
        self.ensure_config_dir()

        # 配置缓存
        self._config_cache = {}
        self._cache_timestamp = {}
        self._cache_max_age = 300  # 缓存5分钟

    def ensure_config_dir(self):
        """确保配置目录存在"""
        self.config_dir.mkdir(exist_ok=True)
        print(f"配置目录: {self.config_dir.absolute()}")

    def save_all_triggers(self, triggers: List[ColorTriggerItem]):
        """保存所有触发器配置"""
        print(f"开始保存配置...")

        # 清理旧的配置文件
        self.clear_old_configs()

        # 保存每个触发器
        for i, trigger in enumerate(triggers):
            filename = f"trigger_{i+1:03d}.json"
            self.save_trigger(trigger, filename)

        print(f"配置保存完成，共保存 {len(triggers)} 个触发器")

    def clear_old_configs(self):
        """清理旧的配置文件"""
        if not self.config_dir.exists():
            return

        # 删除所有 .json 文件
        json_files = list(self.config_dir.glob("*.json"))
        for file in json_files:
            try:
                file.unlink()
                print(f"删除旧配置文件: {file.name}")
            except Exception as e:
                print(f"删除文件失败 {file.name}: {e}")

    def save_trigger(self, trigger: ColorTriggerItem, filename: str):
        """保存单个触发器配置"""
        config_data = self.trigger_to_dict(trigger)
        file_path = self.config_dir / filename

        try:
            with open(file_path, 'w', encoding='utf-8') as f:
                json.dump(config_data, f, indent=2, ensure_ascii=False)
            print(f"保存触发器配置: {filename}")
        except Exception as e:
            print(f"保存配置文件失败 {filename}: {e}")

    def load_all_triggers(self) -> List[ColorTriggerItem]:
        """加载所有触发器配置"""
        print(f"开始加载配置...")
        triggers = []

        if not self.config_dir.exists():
            print(f"配置目录不存在，返回空列表")
            return triggers

        # 获取所有 .json 文件并排序
        json_files = sorted(self.config_dir.glob("*.json"))

        for file_path in json_files:
            try:
                trigger = self.load_trigger(file_path)
                if trigger:
                    triggers.append(trigger)
                    print(f"加载触发器配置: {file_path.name}")
            except Exception as e:
                print(f"加载配置文件失败 {file_path.name}: {e}")

        print(f"配置加载完成，共加载 {len(triggers)} 个触发器")
        return triggers

    def load_trigger(self, file_path: Path) -> ColorTriggerItem:
        """加载单个触发器配置（优化版本 - 支持验证和缓存）"""
        # 检查缓存
        cache_key = str(file_path)
        file_mtime = file_path.stat().st_mtime

        if (cache_key in self._config_cache and
            cache_key in self._cache_timestamp and
            self._cache_timestamp[cache_key] == file_mtime):
            return self._config_cache[cache_key]

        # 加载配置文件
        with open(file_path, 'r', encoding='utf-8') as f:
            config_data = json.load(f)

        # 验证配置数据
        validated_data = self.validate_config_data(config_data, file_path)

        # 转换为触发器对象
        trigger = self.dict_to_trigger(validated_data)

        # 更新缓存
        self._config_cache[cache_key] = trigger
        self._cache_timestamp[cache_key] = file_mtime

        return trigger

    def validate_config_data(self, config_data: Dict[str, Any], file_path: Path) -> Dict[str, Any]:
        """验证和修复配置数据"""
        try:
            # 检查版本并进行迁移
            version = config_data.get("version", "1.0")
            if version != "1.1":
                config_data = self.migrate_config(config_data, version)

            # 验证必需字段
            required_fields = ["name", "color", "algorithm"]
            for field in required_fields:
                if field not in config_data:
                    print(f"警告: 配置文件 {file_path.name} 缺少必需字段 {field}，使用默认值")
                    config_data[field] = self.get_default_value(field)

            # 验证颜色数据
            color_data = config_data.get("color", {})
            if not all(key in color_data for key in ["r", "g", "b"]):
                print(f"警告: 配置文件 {file_path.name} 颜色数据不完整，使用默认值")
                config_data["color"] = {"r": 255, "g": 255, "b": 255}

            # 验证数值范围
            color = config_data["color"]
            for component in ["r", "g", "b"]:
                if not (0 <= color[component] <= 255):
                    print(f"警告: 配置文件 {file_path.name} 颜色分量 {component} 超出范围，已修正")
                    color[component] = max(0, min(255, color[component]))

            return config_data

        except Exception as e:
            print(f"验证配置数据失败 {file_path.name}: {e}")
            return self.get_default_config()

    def migrate_config(self, config_data: Dict[str, Any], from_version: str) -> Dict[str, Any]:
        """配置版本迁移"""
        print(f"迁移配置从版本 {from_version} 到 1.1")

        if from_version == "1.0":
            # 添加检测区域配置
            if "detection_area" not in config_data:
                config_data["detection_area"] = {
                    "detection_mode": "smart_around_center",
                    "detection_offset_x": 30,
                    "detection_offset_y": 30,
                    "detection_area_width": 20,
                    "detection_area_height": 20,
                    "detection_position": "top_right"
                }

        config_data["version"] = "1.1"
        return config_data

    def get_default_value(self, field: str):
        """获取字段的默认值"""
        defaults = {
            "name": "未命名触发器",
            "color": {"r": 255, "g": 255, "b": 255},
            "algorithm": "RGB",
            "tolerance": 10,
            "hsv_tolerances": {"h": 15, "s": 30, "v": 40},
            "enabled": True
        }
        return defaults.get(field)

    def get_default_config(self) -> Dict[str, Any]:
        """获取默认配置"""
        return {
            "name": "默认触发器",
            "color": {"r": 255, "g": 255, "b": 255},
            "algorithm": "RGB",
            "tolerance": 10,
            "hsv_tolerances": {"h": 15, "s": 30, "v": 40},
            "enabled": True,
            "trigger_settings": {
                "trigger_mode": "press",
                "trigger_key": "Space",
                "trigger_count": 0,
                "trigger_interval": 100
            },
            "detection_area": {
                "detection_mode": "smart_around_center",
                "detection_offset_x": 30,
                "detection_offset_y": 30,
                "detection_area_width": 20,
                "detection_area_height": 20,
                "detection_position": "top_right"
            },
            "version": "1.1"
        }

    def trigger_to_dict(self, trigger: ColorTriggerItem) -> Dict[str, Any]:
        """将触发器对象转换为字典"""
        return {
            "name": trigger.name,
            "color": {
                "r": trigger.color[0],
                "g": trigger.color[1],
                "b": trigger.color[2]
            },
            "algorithm": trigger.algorithm,
            "tolerance": trigger.tolerance,
            "hsv_tolerances": trigger.hsv_tolerances,
            "enabled": trigger.enabled,
            "trigger_settings": {
                "trigger_mode": trigger.trigger_mode,
                "trigger_key": trigger.trigger_key,
                "trigger_count": trigger.trigger_count,
                "trigger_interval": trigger.trigger_interval
            },
            "detection_area": {
                "detection_mode": getattr(trigger, 'detection_mode', 'smart_around_center'),
                "detection_offset_x": getattr(trigger, 'detection_offset_x', 30),
                "detection_offset_y": getattr(trigger, 'detection_offset_y', 30),
                "detection_area_width": getattr(trigger, 'detection_area_width', 20),
                "detection_area_height": getattr(trigger, 'detection_area_height', 20),
                "detection_position": getattr(trigger, 'detection_position', 'top_right')
            },
            "version": "1.1"  # 配置文件版本
        }

    def dict_to_trigger(self, data: Dict[str, Any]) -> ColorTriggerItem:
        """将字典转换为触发器对象"""
        # 基本属性
        name = data.get("name", "未命名触发器")
        color_data = data.get("color", {"r": 255, "g": 255, "b": 255})
        color = (color_data["r"], color_data["g"], color_data["b"])
        algorithm = data.get("algorithm", "RGB")
        tolerance = data.get("tolerance", 10)
        hsv_tolerances = data.get("hsv_tolerances", {"h": 15, "s": 30, "v": 40})

        # 创建触发器对象
        trigger = ColorTriggerItem(
            name=name,
            color=color,
            algorithm=algorithm,
            tolerance=tolerance,
            hsv_tolerances=hsv_tolerances
        )

        # 设置启用状态
        trigger.enabled = data.get("enabled", True)

        # 设置触发器配置
        trigger_settings = data.get("trigger_settings", {})
        trigger.trigger_mode = trigger_settings.get("trigger_mode", "press")
        trigger.trigger_key = trigger_settings.get("trigger_key", "Space")
        trigger.trigger_count = trigger_settings.get("trigger_count", 0)
        trigger.trigger_interval = trigger_settings.get("trigger_interval", 100)

        # 设置检测区域配置
        detection_area = data.get("detection_area", {})
        trigger.detection_mode = detection_area.get("detection_mode", "smart_around_center")
        trigger.detection_offset_x = detection_area.get("detection_offset_x", 30)
        trigger.detection_offset_y = detection_area.get("detection_offset_y", 30)
        trigger.detection_area_width = detection_area.get("detection_area_width", 20)
        trigger.detection_area_height = detection_area.get("detection_area_height", 20)
        trigger.detection_position = detection_area.get("detection_position", "top_right")

        return trigger

    def backup_configs(self, backup_dir: str = "config_backup"):
        """备份配置文件"""
        backup_path = Path(backup_dir)

        if self.config_dir.exists() and any(self.config_dir.glob("*.json")):
            try:
                if backup_path.exists():
                    shutil.rmtree(backup_path)
                shutil.copytree(self.config_dir, backup_path)
                print(f"配置文件已备份到: {backup_path.absolute()}")
            except Exception as e:
                print(f"备份配置文件失败: {e}")
        else:
            print("没有配置文件需要备份")

    def get_config_info(self) -> Dict[str, Any]:
        """获取配置信息"""
        if not self.config_dir.exists():
            return {"config_dir": str(self.config_dir), "file_count": 0, "files": []}

        json_files = list(self.config_dir.glob("*.json"))
        return {
            "config_dir": str(self.config_dir.absolute()),
            "file_count": len(json_files),
            "files": [f.name for f in sorted(json_files)]
        }
